package org.yunai.swjg.server.core.role;

import org.yunai.swjg.server.core.common.GameUnit;
import org.yunai.swjg.server.core.util.RolePropertyUtils;
import org.yunai.swjg.server.module.player.SexEnum;
import org.yunai.swjg.server.module.player.VocationEnum;
import org.yunai.yfserver.util.StringUtils;

import java.util.HashMap;
import java.util.Map;

/**
 * 角色属性信息基类
 * User: yunai
 * Date: 13-5-2
 * Time: 下午4:41
 */
public abstract class AbstractRole implements GameUnit {

    /**
     * 角色类型
     */
    private final RoleDef.Unit unit;
    /**
     * 角色的属性定义：角色在游戏过程中对客户端不可见的属性
     */
    protected final RoleFinalProps finalProps;
    /**
     * 如果是double类型，扩大1000倍并四舍五入转化为整数给客户端
     */
    protected final RolePrimaryProps primaryProps;
    /**
     * 角色二级属性。<br />
     * 如果是double类型，扩大1000倍并四舍五入转化为整数给客户端
     */
    protected final RoleSecondaryProps secondaryProps;
    /**
     * 角色字符串属性。
     */
    protected final RoleStringProps stringProps;

    protected AbstractRole(RoleDef.Unit unit) {
        this.unit = unit;
        this.finalProps = new RoleFinalProps();
        this.primaryProps = new RolePrimaryProps();
        this.secondaryProps = new RoleSecondaryProps();
        this.stringProps = new RoleStringProps();
    }

    public void setNickname(String name) {
        stringProps.setString(RoleStringProps.NAME, name);
    }

    public String getNickname() {
        return stringProps.getString(RoleStringProps.NAME, null);
    }

    public void setMedicineStrength(String medicineStrength) {
        stringProps.setString(RoleStringProps.MEDICINE_STRENGTH, medicineStrength);
    }

    public void setMedicineStrength(int medicineLevel, int count) {
        setMedicineProp(RoleStringProps.MEDICINE_STRENGTH, medicineLevel, count);
    }

    public int getMedicineStrengthCount(int medicineLevel) {
        return getMedicinePropCount(RoleStringProps.MEDICINE_STRENGTH, medicineLevel);
    }

    public String getMedicineStrength() {
        return stringProps.getString(RoleStringProps.MEDICINE_STRENGTH, "");
    }

    public int getMedicineStrengthAddTotal() {
        return getMedicinePropAddTotal(RoleStringProps.MEDICINE_STRENGTH);
    }

    public void setMedicineStunt(String medicineStunt) {
        stringProps.setString(RoleStringProps.MEDICINE_STUNT, medicineStunt);
    }

    public void setMedicineStunt(int medicineLevel, int count) {
        setMedicineProp(RoleStringProps.MEDICINE_STUNT, medicineLevel, count);
    }

    public int getMedicineStuntCount(int medicineLevel) {
        return getMedicinePropCount(RoleStringProps.MEDICINE_STUNT, medicineLevel);
    }

    public String getMedicineStunt() {
        return stringProps.getString(RoleStringProps.MEDICINE_STUNT, "");
    }

    public int getMedicineStuntAddTotal() {
        return getMedicinePropAddTotal(RoleStringProps.MEDICINE_STUNT);
    }

    public void setMedicineMagic(String medicineMagic) {
        stringProps.setString(RoleStringProps.MEDICINE_MAGIC, medicineMagic);
    }

    public void setMedicineMagic(int medicineLevel, int count) {
        setMedicineProp(RoleStringProps.MEDICINE_MAGIC, medicineLevel, count);
    }

    public int getMedicineMagicCount(int medicineLevel) {
        return getMedicinePropCount(RoleStringProps.MEDICINE_MAGIC, medicineLevel);
    }

    public String getMedicineMagic() {
        return stringProps.getString(RoleStringProps.MEDICINE_MAGIC, "");
    }

    public int getMedicineMagicAddTotal() {
        return getMedicinePropAddTotal(RoleStringProps.MEDICINE_MAGIC);
    }

    /**
     * 设置某丹药的某等级的数量
     *
     * @param medicinePropKey 丹药属性KEY
     * @param medicineLevel   丹药等级
     * @param count           数量
     */
    private void setMedicineProp(int medicinePropKey, int medicineLevel, int count) {
        Map<Integer, Integer> values = new HashMap<>();
        String[] propStrs = StringUtils.split(stringProps.getString(medicinePropKey, ""), ";");
        for (String propStr : propStrs) {
            int[] propStrInts = StringUtils.splitInt(propStr, "-");
            values.put(propStrInts[0], propStrInts[1]);
        }
        values.put(medicineLevel, count);
        stringProps.setString(medicineLevel, StringUtils.buildString(values, "-", ";"));
    }

    /**
     * @param medicinePropKey 丹药属性KEY
     * @param medicineLevel   丹药等级
     * @return 某丹药某等级的数量
     */
    private int getMedicinePropCount(int medicinePropKey, int medicineLevel) {
        String[] propStrs = StringUtils.split(stringProps.getString(medicinePropKey, ""), ";");
        for (String propStr : propStrs) {
            int[] propStrInts = StringUtils.splitInt(propStr, "-");
            if (propStrInts[0] == medicineLevel) {
                return propStrInts[1];
            }
        }
        return 0;
    }

    /**
     * @param medicinePropKey 丹药属性KEY
     * @return 丹药总属性加成
     */
    private int getMedicinePropAddTotal(int medicinePropKey) {
        int total = 0;
        String[] propStrs = StringUtils.split(stringProps.getString(medicinePropKey, ""), ";");
        for (String propStr : propStrs) {
            int[] propStrInts = StringUtils.splitInt(propStr, "-");
            total += RolePropertyUtils.genMedicinePropAddTotal(propStrInts[0], propStrInts[1]);
        }
        return total;
    }

    public void setVocation(VocationEnum vocationEnum) {
        primaryProps.setShort(RolePrimaryProps.VOCATION, (short) vocationEnum.getIndex());
    }

    public VocationEnum getVocation() {
        return VocationEnum.valueOf(primaryProps.getShort(RolePrimaryProps.VOCATION, (short) 0));
    }

    public void setSex(SexEnum sexEnum) {
        primaryProps.setShort(RolePrimaryProps.SEX, (short) sexEnum.getIndex());
    }

    public SexEnum getSex() {
        return SexEnum.valueOf(primaryProps.getShort(RolePrimaryProps.SEX, (short) 0));
    }

    public int getSceneId() {
        return primaryProps.getInt(RolePrimaryProps.SCENE_ID, 0);
    }

    /**
     * 场景改变时，不推送给客户端
     *
     * @param sceneId 新场景编号
     */
    public void setSceneId(int sceneId) {
        primaryProps.setInt(RolePrimaryProps.SCENE_ID, sceneId);
        primaryProps.resetChanged(RolePrimaryProps.SCENE_ID);
    }

    public short getSceneX() {
        return primaryProps.getShort(RolePrimaryProps.SCENE_X, (short) 0);
    }

    /**
     * 坐标X改变时，不推给客户端
     *
     * @param sceneX 新坐标X
     */
    public void setSceneX(short sceneX) {
        primaryProps.setShort(RolePrimaryProps.SCENE_X, sceneX);
        primaryProps.resetChanged(RolePrimaryProps.SCENE_X);
    }

    public short getSceneY() {
        return primaryProps.getShort(RolePrimaryProps.SCENE_Y, (short) 0);
    }

    /**
     * 坐标Y改变时，不推给客户端
     *
     * @param sceneY 新坐标Y
     */
    public void setSceneY(short sceneY) {
        primaryProps.setShort(RolePrimaryProps.SCENE_Y, sceneY);
        primaryProps.resetChanged(RolePrimaryProps.SCENE_Y);
    }

    public int getScenePreId() {
        return primaryProps.getInt(RolePrimaryProps.SCENE_PRE_ID, 0);
    }

    /**
     * 上一个场景改变时，不推送给客户端
     *
     * @param scenePreId 上一个场景编号
     */
    public void setScenePreId(int scenePreId) {
        primaryProps.setInt(RolePrimaryProps.SCENE_PRE_ID, scenePreId);
        primaryProps.resetChanged(RolePrimaryProps.SCENE_PRE_ID);
    }

    public short getScenePreX() {
        return primaryProps.getShort(RolePrimaryProps.SCENE_PRE_X, (short) 0);
    }

    /**
     * 上一个场景坐标X改变时，不推给客户端
     *
     * @param scenePreX 上一个场景新坐标X
     */
    public void setScenePreX(short scenePreX) {
        primaryProps.setShort(RolePrimaryProps.SCENE_PRE_X, scenePreX);
        primaryProps.resetChanged(RolePrimaryProps.SCENE_PRE_X);
    }

    public short getScenePreY() {
        return primaryProps.getShort(RolePrimaryProps.SCENE_PRE_Y, (short) 0);
    }

    /**
     * 上一个场景坐标Y改变时，不推给客户端
     *
     * @param scenePreY 上一个场景新坐标Y
     */
    public void setScenePreY(short scenePreY) {
        primaryProps.setShort(RolePrimaryProps.SCENE_PRE_Y, scenePreY);
        primaryProps.resetChanged(RolePrimaryProps.SCENE_PRE_Y);
    }

    public void setLevel(short level) {
        primaryProps.setShort(RolePrimaryProps.LEVEL, level);
    }

    public short getLevel() {
        return primaryProps.getShort(RolePrimaryProps.LEVEL, (short) 0);
    }

    public void setExp(int exp) {
        primaryProps.setInt(RolePrimaryProps.EXP, exp);
    }

    public int getExp() {
        return primaryProps.getInt(RolePrimaryProps.EXP, 0);
    }

    public void setCoin(int coin) {
        primaryProps.setInt(RolePrimaryProps.COIN, coin);
    }

    public int getCoin() {
        return primaryProps.getInt(RolePrimaryProps.COIN, 0);
    }

    public void setGold(int gold) {
        primaryProps.setInt(RolePrimaryProps.GOLD, gold);
    }

    public int getGold() {
        return primaryProps.getInt(RolePrimaryProps.GOLD, 0);
    }

    public void setReputation(int reputation) {
        primaryProps.setInt(RolePrimaryProps.REPUTATION, reputation);
    }

    public int getReputation() {
        return primaryProps.getInt(RolePrimaryProps.REPUTATION, 0);
    }

    public void setSoul(int wood) {
        primaryProps.setInt(RolePrimaryProps.SOUL, wood);
    }

    public int getSoul() {
        return primaryProps.getInt(RolePrimaryProps.SOUL, 0);
    }

    public Long getLastLoginTime() {
        return finalProps.getLong(RoleFinalProps.LAST_LOGIN_TIME, 0L);
    }

    public void setLastLoginTime(Long lastLoginTime) {
        finalProps.setLong(RoleFinalProps.LAST_LOGIN_TIME, lastLoginTime);
    }

    public Long getLastLogoutTime() {
        return finalProps.getLong(RoleFinalProps.LAST_LOGOUT_TIME, 0L);
    }

    public void setLastLogoutTime(Long lastLogoutTime) {
        finalProps.setLong(RoleFinalProps.LAST_LOGOUT_TIME, lastLogoutTime);
    }

    public String getLastIP() {
        return finalProps.getString(RoleFinalProps.LAST_IP, null);
    }

    public void setLastIp(String lastIp) {
        finalProps.setString(RoleFinalProps.LAST_IP, lastIp);
    }

    public Long getCreateRoleTime() {
        return finalProps.getLong(RoleFinalProps.CREATE_ROLE_TIME, 0L);
    }

    public void setCreateRoleTime(Long createRoleTime) {
        finalProps.setLong(RoleFinalProps.CREATE_ROLE_TIME, createRoleTime);
    }

    public Long getTotalOnlineTime() {
        return finalProps.getLong(RoleFinalProps.TOTAL_ONLINE_TIME, 0L);
    }

    public void setTotalOnlineTime(Long totalOnlineTime) {
        finalProps.setLong(RoleFinalProps.TOTAL_ONLINE_TIME, totalOnlineTime);
    }

    public Long getLastLastLoginTime() {
        return finalProps.getLong(RoleFinalProps.LAST_LAST_LOGIN_TIME, 0L);
    }

    public void setLastLastLoginTime(Long lastLastLoginTime) {
        finalProps.setLong(RoleFinalProps.LAST_LAST_LOGIN_TIME, lastLastLoginTime);
    }

    public String getLastLastIp() {
        return finalProps.getString(RoleFinalProps.LAST_LAST_IP, null);
    }

    public void setLastLastIp(String lastLastIp) {
        finalProps.setString(RoleFinalProps.LAST_LAST_IP, lastLastIp);
    }

    public int getDevelopStrength() {
        return primaryProps.getInt(RolePrimaryProps.DEVELOP_STRENGTH, 0);
    }

    public void setDevelopStrength(int developStrength) {
        primaryProps.setInt(RolePrimaryProps.DEVELOP_STRENGTH, developStrength);
    }

    public int getDevelopStunt() {
        return primaryProps.getInt(RolePrimaryProps.DEVELOP_STUNT, 0);
    }

    public void setDevelopStunt(int developStunt) {
        primaryProps.setInt(RolePrimaryProps.DEVELOP_STUNT, developStunt);
    }

    public int getDevelopMagic() {
        return primaryProps.getInt(RolePrimaryProps.DEVELOP_MAGIC, 0);
    }

    public void setDevelopMagic(int developMagic) {
        primaryProps.setInt(RolePrimaryProps.DEVELOP_MAGIC, developMagic);
    }

    public int getSpecialSkill() {
        return primaryProps.getInt(RolePrimaryProps.SPECIAL_SKILL, 0);
    }

    public void setSpecialSkill(int specialSkill) {
        primaryProps.setInt(RolePrimaryProps.SPECIAL_SKILL, specialSkill);
    }

    public int getStrength() {
        return secondaryProps.getInt(RoleSecondaryProps.STRENGTH, 0);
    }

    public void setStrength(int strength) {
        secondaryProps.setInt(RoleSecondaryProps.STRENGTH, strength);
    }

    public int getStunt() {
        return secondaryProps.getInt(RoleSecondaryProps.STUNT, 0);
    }

    public void setStunt(int stunt) {
        secondaryProps.setInt(RoleSecondaryProps.STUNT, stunt);
    }

    public int getMagic() {
        return secondaryProps.getInt(RoleSecondaryProps.MAGIC, 0);
    }

    public void setMagic(int magic) {
        secondaryProps.setInt(RoleSecondaryProps.MAGIC, magic);
    }

    public int getStrengthAttack() {
        return secondaryProps.getInt(RoleSecondaryProps.STRENGTH_ATTACK, 0);
    }

    public void setStrengthAttack(int strengthAttack) {
        secondaryProps.setInt(RoleSecondaryProps.STRENGTH_ATTACK, strengthAttack);
        secondaryProps.resetChanged(RoleSecondaryProps.STRENGTH_ATTACK);
    }

    public int getStuntAttack() {
        return secondaryProps.getInt(RoleSecondaryProps.STUNT_ATTACK, 0);
    }

    public void setStuntAttack(int stuntAttack) {
        secondaryProps.setInt(RoleSecondaryProps.STUNT_ATTACK, stuntAttack);
        secondaryProps.resetChanged(RoleSecondaryProps.STUNT_ATTACK);
    }

    public int getMagicAttack() {
        return secondaryProps.getInt(RoleSecondaryProps.MAGIC_ATTACK, 0);
    }

    public void setMagicAttack(int strengthAttack) {
        secondaryProps.setInt(RoleSecondaryProps.MAGIC_ATTACK, strengthAttack);
        secondaryProps.resetChanged(RoleSecondaryProps.MAGIC_ATTACK);
    }

    public int getStrengthDefense() {
        return secondaryProps.getInt(RoleSecondaryProps.STRENGTH_DEFENSE, 0);
    }

    public void setStrengthDefense(int strengthDefense) {
        secondaryProps.setInt(RoleSecondaryProps.STRENGTH_DEFENSE, strengthDefense);
        secondaryProps.resetChanged(RoleSecondaryProps.STRENGTH_DEFENSE);
    }

    public int getStuntDefense() {
        return secondaryProps.getInt(RoleSecondaryProps.STUNT_DEFENSE, 0);
    }

    public void setStuntDefense(int stuntDefense) {
        secondaryProps.setInt(RoleSecondaryProps.STUNT_DEFENSE, stuntDefense);
        secondaryProps.resetChanged(RoleSecondaryProps.STUNT_DEFENSE);
    }

    public int getMagicDefense() {
        return secondaryProps.getInt(RoleSecondaryProps.MAGIC_DEFENSE, 0);
    }

    public void setMagicDefense(int magicDefense) {
        secondaryProps.setInt(RoleSecondaryProps.MAGIC_DEFENSE, magicDefense);
        secondaryProps.resetChanged(RoleSecondaryProps.MAGIC_DEFENSE);
    }

    public int getHpMax() {
        return secondaryProps.getInt(RoleSecondaryProps.HP_MAX, 0);
    }

    public void setHpMax(int hpMax) {
        secondaryProps.setInt(RoleSecondaryProps.HP_MAX, hpMax);
    }

    public int getHpCur() {
        return secondaryProps.getInt(RoleSecondaryProps.HP_CUR, 0);
    }

    public void setHpCur(int hpCur) {
        secondaryProps.setInt(RoleSecondaryProps.HP_CUR, hpCur);
        secondaryProps.resetChanged(RoleSecondaryProps.HP_CUR);
    }

    public int getCrit() {
        return secondaryProps.getInt(RoleSecondaryProps.CRIT, 0);
    }

    public void setCrit(int crit) {
        secondaryProps.setInt(RoleSecondaryProps.CRIT, crit);
        secondaryProps.resetChanged(RoleSecondaryProps.CRIT);
    }

    public int getHit() {
        return secondaryProps.getInt(RoleSecondaryProps.HIT, 0);
    }

    public void setHit(int hit) {
        secondaryProps.setInt(RoleSecondaryProps.HIT, hit);
        secondaryProps.resetChanged(RoleSecondaryProps.HIT);
    }

    public int getPoJi() {
        return secondaryProps.getInt(RoleSecondaryProps.POJI, 0);
    }

    public void setPoJi(int poji) {
        secondaryProps.setInt(RoleSecondaryProps.POJI, poji);
        secondaryProps.resetChanged(RoleSecondaryProps.POJI);
    }

    public int getBiSha() {
        return secondaryProps.getInt(RoleSecondaryProps.BISHA, 0);
    }

    public void setBiSha(int bisha) {
        secondaryProps.setInt(RoleSecondaryProps.BISHA, bisha);
        secondaryProps.resetChanged(RoleSecondaryProps.BISHA);
    }

    public int getToughness() {
        return secondaryProps.getInt(RoleSecondaryProps.TOUGHNESS, 0);
    }

    public void setToughness(int toughness) {
        secondaryProps.setInt(RoleSecondaryProps.TOUGHNESS, toughness);
        secondaryProps.resetChanged(RoleSecondaryProps.TOUGHNESS);
    }

    public int getDodge() {
        return secondaryProps.getInt(RoleSecondaryProps.DODGE, 0);
    }

    public void setDodge(int dodge) {
        secondaryProps.setInt(RoleSecondaryProps.DODGE, dodge);
        secondaryProps.resetChanged(RoleSecondaryProps.DODGE);
    }

    public int getBlock() {
        return secondaryProps.getInt(RoleSecondaryProps.BLOCK, 0);
    }

    public void setBlock(int block) {
        secondaryProps.setInt(RoleSecondaryProps.BLOCK, block);
        secondaryProps.resetChanged(RoleSecondaryProps.BLOCK);
    }

    public int getXianGong() {
        return secondaryProps.getInt(RoleSecondaryProps.XIANGONG, 0);
    }

    public void setXianGong(int xianGong) {
        secondaryProps.setInt(RoleSecondaryProps.XIANGONG, xianGong);
        secondaryProps.resetChanged(RoleSecondaryProps.XIANGONG);
    }

    public int getPower() {
        return secondaryProps.getInt(RoleSecondaryProps.POWER, 0);
    }

    public void setPower(int power) {
        secondaryProps.setInt(RoleSecondaryProps.POWER, power);
        secondaryProps.resetChanged(RoleSecondaryProps.POWER);
    }

    public int getMingLi() {
        return secondaryProps.getInt(RoleSecondaryProps.MINGLI, 0);
    }

    public void setMingLi(int mingLi) {
        secondaryProps.setInt(RoleSecondaryProps.MINGLI, mingLi);
        secondaryProps.resetChanged(RoleSecondaryProps.MINGLI);
    }

    /**
     * 清除属性修改标记
     */
    public void clearPropsChanged() {
        this.primaryProps.resetChanged();
        this.secondaryProps.resetChanged();
        this.stringProps.resetChanged();
    }
}
